package com.atguigu.gmall.item.comp;

import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.Arrays;
import java.util.UUID;

@Component
@Slf4j
public class RedisDistLock {
    @Autowired
    StringRedisTemplate redisTemplate;

    public String lock(){
        String token = UUID.randomUUID().toString();
        //枷锁 加入自动过期时间 防止死锁
        Boolean absent = redisTemplate.opsForValue().setIfAbsent("lock", token,Duration.ofSeconds(10));
        //枷锁失败继续加 一直到成功 阻塞式加锁
        //自选锁代码
        while (!absent){
            //只要没加到 疯狂重试
            try {
                Thread.sleep(20);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            absent = redisTemplate.opsForValue().setIfAbsent("lock","hhh");
        }
        //可能来不及加锁 没来的及设置过期时间
        //加锁成功
        //给锁加过期时间
        //redisTemplate.expire("lock", Duration.ofSeconds(12));

        return token;
    }

    //解锁
    public void unLock(String token) {
        //可能删除别人的锁
        //
//        if (token.equals(redisTemplate.opsForValue().get("lock"))){
//            redisTemplate.delete("lock");
//        }else {
//            log.info("别人的锁");
//        }
        //lua脚本 原子性的
        String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
                "then\n" +
                "    return redis.call(\"del\",KEYS[1])\n" +
                "else\n" +
                "    return 0\n" +
                "end";
        //返回1就是删除成功
        //返回0 1）别人的锁 2）已经被删除了 没有这个key
        Long lock = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class),
                Arrays.asList("lock"), token);
        if (lock> 0){
            log.info("解锁："+token);
        }
    }
}
